package com.szsh.aiot.hsm.dao;

import com.szsh.aiot.hsm.utils.Hash163;
import org.influxdb.InfluxDB;
import org.influxdb.dto.Query;
import org.influxdb.dto.QueryResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class InfluxDao {
    private static final Logger LOGGER = LoggerFactory.getLogger(InfluxDao.class);

    private final InfluxDB influxDB;

    private final Hash163 hash163;

    public InfluxDao(InfluxDB influxDB, Hash163 hash163) {
        this.influxDB = influxDB;
        this.hash163 = hash163;
    }

    /**
     * 查询influxDB，返回流量推送数据集合
     *
     * @param deviceId 设备ID
     * @return 推送数据集合
     */
    public List<List<Object>> getFlowPushList(String deviceId) {
        // 查询近一天的流量数据
        // 按照20分钟为间隔查询，influxDB自动求和；该查询会多查一条前一天开始时间取整的数据
        StringBuilder querySB = new StringBuilder();
        querySB.append("select sum(\"txBytes\")/1024 as txBytes from flow_push where hashDeviceID='")
                .append(hash163.sHash(deviceId)).append("' and deviceID=").append(deviceId)
                .append(" and time>now()-1d")
                .append(" group by time(20m) fill(0) tz('Asia/Shanghai')");
        LOGGER.info("influxDB query:{}", querySB);
        Query query = new Query(querySB.toString());
        QueryResult queryResult = influxDB.query(query);
        List<QueryResult.Result> results = queryResult.getResults();
        if (results == null) {
            return new ArrayList<>();
        }
        QueryResult.Result result = results.get(0);
        List<QueryResult.Series> rsp = result.getSeries();
        if (rsp != null) {
            return rsp.get(0).getValues();
        }
        return new ArrayList<>();
    }

    /**
     * 查询influxDB流量告警信息 从告警表中获取时间 从推送数据中获取流量
     *
     * @param deviceId 设备ID
     * @return  流量告警信息
     */
    public List<List<Object>> getFlowAlarmData(String deviceId) {
        List<List<Object>> resultList = new ArrayList<>();
        // 流量告警信息
        List<List<Object>> alarmList = getFlowAlarmList(deviceId);
        if (alarmList == null || alarmList.isEmpty()) {
            return resultList;
        }
        // 查询流量推送信息
        for (List<Object> objects : alarmList) {
            String date = (String) objects.get(0);
            StringBuilder querySB = new StringBuilder();
            querySB.append("select first(\"txBytes\")/1024 as txBytes from flow_push where "
                            + "hashDeviceID='").append(hash163.sHash(deviceId)).append("' and deviceID=")
                    .append(deviceId).append(" and time='").append(date)
                    .append("' tz('Asia/Shanghai')");
            LOGGER.info("influxDB query:{}", querySB);
            Query query = new Query(querySB.toString());
            QueryResult queryResult = influxDB.query(query);
            List<QueryResult.Result> results = queryResult.getResults();
            if (results != null && results.get(0).getSeries() != null) {
                resultList.addAll(results.get(0).getSeries().get(0).getValues());
            }
        }
        return resultList;
    }

    /**
     * 查询最新流量告警信息，最多5条
     *
     * @param deviceId 设备ID
     * @return 流量告警信息
     */
    private List<List<Object>> getFlowAlarmList(String deviceId) {
        List<List<Object>> alarmList = new ArrayList<>();
        StringBuilder alarmQuery = new StringBuilder();
        // 查询最近5条流量告警信息
        alarmQuery.append("select * from flow_alarm where hashDeviceID='")
                .append(hash163.sHash(deviceId)).append("' and deviceID=").append(deviceId)
                .append(" and time>now()-1d order by time desc limit 5 tz('Asia/Shanghai')");
        LOGGER.info("influxDB query:{}", alarmQuery);
        Query query = new Query(alarmQuery.toString());
        QueryResult queryResult = influxDB.query(query);
        List<QueryResult.Result> results = queryResult.getResults();
        if (results == null) {
            return null;
        }
        QueryResult.Result result = results.get(0);
        List<QueryResult.Series> rsp = result.getSeries();
        if (rsp != null) {
            alarmList = rsp.get(0).getValues();
        }
        return alarmList;
    }
}
